﻿using System;
using System.Drawing;
using Kaleida.ServiceMonitor.Model;
using Kaleida.ServiceMonitor.Model.Runtime;
using NUnit.Framework;

namespace Kaleida.UnitTests.Model.Runtime
{
    [TestFixture]
    public class DefaultStatePresentationTests
    {
        [Test]
        public void TestGet10FootBackgroundColourIsGreyWhenNoScript()
        {
            var state = new MonitorState();
            var presentation = new DefaultStatePresentation(state);
            
            Assert.AreEqual(Color.Gray, presentation.GetNotificationColour());
        }

        [Test]
        public void TestGet10FootBackgroundColourIsGreyWhenNotRunning()
        {
            var state = new MonitorState();
            state.ScriptCompiled(ScriptCompilation.Success(new CompiledScript()));

            Assert.IsFalse(state.IsMonitoring);

            var presentation = new DefaultStatePresentation(state);

            Assert.AreEqual(Color.Gray, presentation.GetNotificationColour());
        }


        [Test]
        public void TestGet10FootBackgroundColourIsGreenWhenRunningAndNoErrors()
        {
            var state = new MonitorState();
            state.ScriptCompiled(ScriptCompilation.Success(new CompiledScript()));
            state.StartMonitoring();

            var presentation = new DefaultStatePresentation(state);

            Assert.IsTrue(state.IsMonitoring);
            Assert.IsFalse(state.HasOperationFailures);
            
            Assert.AreEqual(Color.LightGreen, presentation.GetNotificationColour());
        }

        [Test]
        public void TestGet10FootBackgroundColourChangesAsErrorsAccumulate()
        {
            var state = new MonitorState ();
            state.ScriptCompiled(ScriptCompilation.Success(new CompiledScript()));
            state.StartMonitoring();

            var presentation = new DefaultStatePresentation(state);

            Assert.IsTrue(state.IsMonitoring);
            Assert.IsFalse(state.HasOperationFailures);

            state.FlagError();
            Assert.AreEqual(Color.Yellow, presentation.GetNotificationColour());
            state.FlagError();
            Assert.AreEqual(Color.Orange, presentation.GetNotificationColour());

            state.IncrementErrorsCountBy(8);
            Assert.AreEqual(10, state.OperationErrorCount);

            Assert.AreEqual(Color.Orange, presentation.GetNotificationColour());
            state.FlagError();
            Assert.AreEqual(Color.LightCoral, presentation.GetNotificationColour());

            state.IncrementErrorsCountBy(89);
            Assert.AreEqual(100, state.OperationErrorCount);

            Assert.AreEqual(Color.LightCoral, presentation.GetNotificationColour());

            state.FlagError();
            Assert.AreEqual(Color.Crimson, presentation.GetNotificationColour());

            state.IncrementErrorsCountBy(1000);
            Assert.AreEqual(Color.Crimson, presentation.GetNotificationColour());
        }

        [Test]
        public void TestGet10FootSymbolWhenNotRunning()
        {
            var state = new MonitorState();
            var presentation = new DefaultStatePresentation(state);

            Assert.IsFalse(state.IsMonitoring);

            Assert.AreEqual("", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootSymbolWhenNotRunningAndHasErrors()
        {
            var state = new MonitorState();
            state.FlagError();

            Assert.IsFalse(state.IsMonitoring);
            Assert.IsTrue(state.HasOperationFailures);

            var presentation = new DefaultStatePresentation(state);
            Assert.AreEqual(":-(", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootSymbolWhenRunningAndNoErrors()
        {
            var state = new MonitorState();
            state.ScriptCompiled(ScriptCompilation.Success(new CompiledScript()));
            state.StartMonitoring();

            var presentation = new DefaultStatePresentation(state);

            Assert.IsTrue(state.IsMonitoring);
            Assert.IsFalse(state.HasOperationFailures);

            Assert.AreEqual(":-)", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootSymbolWhenRunningAndHasErrors()
        {
            var state = new MonitorState();
            state.ScriptCompiled(ScriptCompilation.Success(new CompiledScript()));
            state.StartMonitoring();
            state.FlagError();

            var presentation = new DefaultStatePresentation(state);

            Assert.IsTrue(state.IsMonitoring);
            Assert.IsTrue(state.HasOperationFailures);

            Assert.AreEqual(":-(", presentation.GetNotificationWord());
        }

        [Test]
        public void TestGet10FootStatusMessage()
        {
            var state = new MonitorState();

            var presentation = new DefaultStatePresentation(state);

            Assert.AreEqual("", presentation.GetStateDetail());

            state.ScriptCompiled(ScriptCompilation.Success(new CompiledScript()));

            Assert.AreEqual("", presentation.GetStateDetail());

            state.StartMonitoring();

            state.FlagError(new OperationError("First Error", new DateTime(2012, 1, 5)));
            Assert.AreEqual("1 error:\r\n    05-Jan-2012 00:00:00 First Error\r\n", presentation.GetStateDetail());
            state.FlagError(new OperationError("Second Error", new DateTime(2012, 1, 6)));
            Assert.AreEqual("2 errors:\r\n    First:  05-Jan-2012 00:00:00 First Error\r\n    Latest: 06-Jan-2012 00:00:00 Second Error\r\n", presentation.GetStateDetail());
            state.FlagError(new OperationError("Third Error", new DateTime(2012, 1, 7)));
            Assert.AreEqual("3 errors:\r\n    First:  05-Jan-2012 00:00:00 First Error\r\n    Latest: 07-Jan-2012 00:00:00 Third Error\r\n", presentation.GetStateDetail());
            state.StopMonitoring();
            Assert.AreEqual("3 errors:\r\n    First:  05-Jan-2012 00:00:00 First Error\r\n    Latest: 07-Jan-2012 00:00:00 Third Error\r\n", presentation.GetStateDetail());
        }
    }

    internal static class TestHelper
    {
        internal static void IncrementErrorsCountBy(this MonitorState state, int count)
        {
            for (int i = 0; i < count; i++)
                state.FlagError();
        }

        internal static void FlagError(this MonitorState state)
        {
            state.FlagError(new OperationError("Dummy Error", DateTime.Now));
        }
    }
}
